// ignore_for_file: non_constant_identifier_names

import 'dart:io';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:dart_bean/cass_info.dart';
import 'package:dart_bean/setting.dart';
import 'package:dart_bean/util/ext.dart';
import 'package:dart_bean/util/field_feature.dart';
import 'package:dart_bean/field_info.dart';
import 'package:dart_bean/util/visitor.dart';

class CustomJsonConverterFeature extends FieldFeature {
  static final Set<DartClassDeclaration> _jsonConverters = {};
  late final _jsonConverterNames = _jsonConverters.map((e) => e.self.name.toString());

  @override
  String? getFromJsonMethod(FieldInfo field, String type) {
    final jsonConverterName = _getCustomJsonConverterName(field);
    if (jsonConverterName != null) {
      return 'const $jsonConverterName().fromJson';
    }
    return null;
  }

  @override
  String? getConvert(FieldInfo field) {
    final fromJson = getFromJsonMethod(field, '');
    if (fromJson != null) {
      final jsonConvert = jsonCastParamName;
      String convert = 'convert';
      String type = getNotNullType(field.type);
      final String json = mediator.getJsonParam(field)!;
      List<String> params = [json];

      params.add('fromJson:$fromJson');
      buildDefaultValue(field, params);
      return "$jsonConvert.$convert<$type>(${params.join(',')})";
    }
    return null;
  }

  @override
  String? mergeToJsonRightValue(FieldInfo field, String instance, String type) {
    final jsonConverterName = _getCustomJsonConverterName(field);
    if (jsonConverterName != null) {
      return 'const $jsonConverterName().toJson($instance)';
    }
    return null;
  }

  String? _getCustomJsonConverterName(FieldInfo field) {
    final jsonConverterAnnotation = field.self.metadata.firstOrNull((a) => _jsonConverterNames.contains(a.name.name));
    return jsonConverterAnnotation?.name.name;
  }

  static visitClassDeclaration(File file, ClassDeclaration node) {
    if (_isCustomJsonConverter(node)) _jsonConverters.add(DartClassDeclaration(file, node));
  }

  static bool _isCustomJsonConverter(ClassDeclaration node) {
    return node.extendsClause?.superclass.name.name == 'JsonConverter';
  }
}
